From 6452aeef3cce6b74262a604a770af3a535f3bc09 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 12 Jun 2019 01:34:19 +0000 Subject: [PATCH] link button: Use new context menu api --- gtk/gtklinkbutton.c | 120 ++++++++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 49 deletions(-) diff --git a/gtk/gtklinkbutton.c b/gtk/gtklinkbutton.c index f867b63c91..7c68d9380f 100644 --- a/gtk/gtklinkbutton.c +++ b/gtk/gtklinkbutton.c @@ -60,8 +60,7 @@ #include "gtklabel.h" #include "gtkmain.h" #include "gtkmarshalers.h" -#include "gtkmenu.h" -#include "gtkmenuitem.h" +#include "gtkpopovermenu.h" #include "gtkprivate.h" #include "gtkshow.h" #include "gtksizerequest.h" @@ -97,6 +96,7 @@ struct _GtkLinkButtonPrivate gboolean visited; + GActionMap *context_actions; GtkWidget *popup_menu; }; @@ -223,6 +223,43 @@ gtk_link_button_class_init (GtkLinkButtonClass *klass) gtk_widget_class_set_css_name (widget_class, I_("button")); } +static void copy_activate_cb (GSimpleAction *action, + GVariant *parameter, + gpointer user_data); + +static void +gtk_link_button_add_context_actions (GtkLinkButton *link_button) +{ + GtkLinkButtonPrivate *priv = gtk_link_button_get_instance_private (link_button); + + GActionEntry entries[] = { + { "copy-clipboard", copy_activate_cb, NULL, NULL, NULL }, + }; + + GSimpleActionGroup *actions = g_simple_action_group_new (); + + priv->context_actions = G_ACTION_MAP (actions); + + g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), link_button); + + gtk_widget_insert_action_group (GTK_WIDGET (link_button), "context", G_ACTION_GROUP (actions)); +} + +static GMenuModel * +gtk_link_button_get_menu_model (void) +{ + GMenu *menu, *section; + + menu = g_menu_new (); + + section = g_menu_new (); + g_menu_append (section, _("_Copy URL"), "context.copy-clipboard"); + g_menu_append_section (menu, NULL, G_MENU_MODEL (section)); + g_object_unref (section); + + return G_MENU_MODEL (menu); +} + static void gtk_link_button_init (GtkLinkButton *link_button) { @@ -261,6 +298,7 @@ gtk_link_button_init (GtkLinkButton *link_button) gtk_style_context_add_class (context, "link"); gtk_widget_set_cursor_from_name (GTK_WIDGET (link_button), "pointer"); + gtk_link_button_add_context_actions (link_button); } static void @@ -270,7 +308,10 @@ gtk_link_button_finalize (GObject *object) GtkLinkButtonPrivate *priv = gtk_link_button_get_instance_private (link_button); g_free (priv->uri); - + + g_clear_object (&priv->context_actions); + g_clear_pointer (&priv->popup_menu, gtk_widget_unparent); + G_OBJECT_CLASS (gtk_link_button_parent_class)->finalize (object); } @@ -320,19 +361,11 @@ gtk_link_button_set_property (GObject *object, } static void -popup_menu_detach (GtkWidget *attach_widget, - GtkMenu *menu) -{ - GtkLinkButton *link_button = GTK_LINK_BUTTON (attach_widget); - GtkLinkButtonPrivate *priv = gtk_link_button_get_instance_private (link_button); - - priv->popup_menu = NULL; -} - -static void -copy_activate_cb (GtkWidget *widget, - GtkLinkButton *link_button) +copy_activate_cb (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) { + GtkLinkButton *link_button = user_data; GtkLinkButtonPrivate *priv = gtk_link_button_get_instance_private (link_button); gdk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (link_button)), @@ -340,45 +373,35 @@ copy_activate_cb (GtkWidget *widget, } static void -gtk_link_button_do_popup (GtkLinkButton *link_button, - const GdkEvent *event) +gtk_link_button_do_popup (GtkLinkButton *link_button, + double x, + double y) { GtkLinkButtonPrivate *priv = gtk_link_button_get_instance_private (link_button); - if (gtk_widget_get_realized (GTK_WIDGET (link_button))) + if (!priv->popup_menu) { - GtkWidget *menu_item; - - if (priv->popup_menu) - gtk_widget_destroy (priv->popup_menu); - - priv->popup_menu = gtk_menu_new (); - gtk_style_context_add_class (gtk_widget_get_style_context (priv->popup_menu), - GTK_STYLE_CLASS_CONTEXT_MENU); + GMenuModel *model; - gtk_menu_attach_to_widget (GTK_MENU (priv->popup_menu), - GTK_WIDGET (link_button), - popup_menu_detach); + model = gtk_link_button_get_menu_model (); + priv->popup_menu = gtk_popover_menu_new_from_model (GTK_WIDGET (link_button), model); + gtk_popover_set_position (GTK_POPOVER (priv->popup_menu), GTK_POS_BOTTOM); - menu_item = gtk_menu_item_new_with_mnemonic (_("Copy URL")); - g_signal_connect (menu_item, "activate", - G_CALLBACK (copy_activate_cb), link_button); - gtk_widget_show (menu_item); - gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menu_item); + gtk_popover_set_has_arrow (GTK_POPOVER (priv->popup_menu), FALSE); + gtk_widget_set_halign (priv->popup_menu, GTK_ALIGN_START); - if (event && gdk_event_triggers_context_menu (event)) - gtk_menu_popup_at_pointer (GTK_MENU (priv->popup_menu), event); - else - { - gtk_menu_popup_at_widget (GTK_MENU (priv->popup_menu), - GTK_WIDGET (link_button), - GDK_GRAVITY_SOUTH, - GDK_GRAVITY_NORTH_WEST, - event); + g_object_unref (model); + } - gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->popup_menu), FALSE); - } + if (x != -1 && y != -1) + { + GdkRectangle rect = { x, y, 1, 1 }; + gtk_popover_set_pointing_to (GTK_POPOVER (priv->popup_menu), &rect); } + else + gtk_popover_set_pointing_to (GTK_POPOVER (priv->popup_menu), NULL); + + gtk_popover_popup (GTK_POPOVER (priv->popup_menu)); } static void @@ -399,7 +422,7 @@ gtk_link_button_pressed_cb (GtkGestureClick *gesture, if (gdk_event_triggers_context_menu (event) && priv->uri != NULL) { - gtk_link_button_do_popup (link_button, event); + gtk_link_button_do_popup (link_button, x, y); gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED); } else @@ -445,9 +468,8 @@ gtk_link_button_clicked (GtkButton *button) static gboolean gtk_link_button_popup_menu (GtkWidget *widget) { - gtk_link_button_do_popup (GTK_LINK_BUTTON (widget), NULL); - - return TRUE; + gtk_link_button_do_popup (GTK_LINK_BUTTON (widget), -1, -1); + return TRUE; } static void -- 2.30.2